 module SendCtrl(
  input clk_50M,
  input rstn,
  input en,
  input [31:0] FreData,
  input [31:0] PWData,
  input [31:0] DCData,
  output uart_tx
);


localparam NUM_Bytes = 12;
localparam NUM_bits  = NUM_Bytes * 8;

// uart_tx模块
reg send_en;
reg [7:0] send_data;

wire w_uart_en;
wire [7:0] w_uart_data;
wire w_uart_busy;

UART_Send UART_Send_inst
(
  .clk_50M( clk_50M ),
  .rstn( rstn ),
  .uart_en( w_uart_en ),
  .uart_data( w_uart_data ),
  .uart_busy( w_uart_busy ),
  .uart_tx( uart_tx )
);

// 获取en下降沿
reg [1:0] r_en;
wire neg_en;

always @(posedge clk_50M, negedge rstn) begin
  if(!rstn) begin
    r_en <= 2'd0;
  end
  else begin
    r_en <= {r_en[0], en};
  end
end

assign neg_en = (r_en[1]) & (~r_en[0]);


// 获取uart_busy下降沿(发送单字节完成)
reg [1:0] r_uart_busy;
wire neg_uart_busy;

always @(posedge clk_50M, negedge rstn) begin
  if(!rstn) begin
    r_uart_busy <= 2'd0;
  end
  else begin
    r_uart_busy <= {r_uart_busy[0], w_uart_busy};
  end
end

assign neg_uart_busy = (r_uart_busy[1]) & (~r_uart_busy[0]);


// 发送字节计数
wire end_cnt_byte;
reg [3:0] cnt_byte;

always @(posedge clk_50M, negedge rstn) begin
  if(!rstn) begin
    cnt_byte <= 4'd0;
  end
  else if(neg_uart_busy) begin
    if(end_cnt_byte) begin
      cnt_byte <= 4'd0;
    end
    else begin
      cnt_byte <= cnt_byte + 4'd1;
    end
  end
  else begin
    cnt_byte <= cnt_byte;
  end
end

assign end_cnt_byte = (neg_uart_busy) &&(cnt_byte == NUM_Bytes - 1);

// 状态
localparam IDLE = 3'b001; // 空闲状态
localparam S1   = 3'b010; // 准备状态，使能、装载数据
localparam S2   = 3'b100; // 发送状态

// 状态机转移条件
wire IDLE_2_S1_start;
wire S1_2_S2_start;
wire S2_2_IDLE_start;
wire S2_2_S1_start;

reg [3:0] state_c;
reg [3:0] state_n;

// 状态机转移描述
always @(posedge clk_50M, negedge rstn) begin
  if(!rstn)
    state_c <= IDLE;
  else
    state_c <= state_n;
end

// 转移条件描述
always @(*) begin
  case (state_c)
    IDLE: begin
      if(IDLE_2_S1_start)
        state_n = S1;
      else
        state_n = state_c;
    end
    S1: begin
      if(S1_2_S2_start)
        state_n = S2;
      else
        state_n = state_c;
    end
    S2: begin
      if(S2_2_IDLE_start)
        state_n = IDLE;
      else if(S2_2_S1_start)
        state_n = S1;
      else
        state_n = state_c;
    end
    default: 
      state_n = IDLE;
  endcase
end

assign IDLE_2_S1_start = (state_c == IDLE) &&(neg_en);
assign S1_2_S2_start   = (state_c == S1  ) &&(send_en);
assign S2_2_IDLE_start = (state_c == S2  ) &&(end_cnt_byte);
assign S2_2_S1_start   = (state_c == S2  ) &&(!end_cnt_byte) &&(neg_uart_busy);

// 状态输出
reg [NUM_bits-1:0] buf_data;

always @(posedge clk_50M, negedge rstn) begin
  if(!rstn) begin
    send_data <= 8'd0;
    buf_data <= 0;
  end
  else if(state_c == IDLE) begin
    send_data <= 8'd0;
    buf_data <= {FreData, PWData, DCData};
  end
  else if((state_c == S1) &&(!send_en)) begin
    send_data <= buf_data[7:0];
    buf_data <= {8'd0, buf_data[NUM_bits-1:8]};
  end
  else begin
    send_data <= send_data;
    buf_data <= buf_data;
  end
end

assign w_uart_data = send_data;

always @(posedge clk_50M, negedge rstn) begin
  if(!rstn)
    send_en <= 1'd0;
  else if(state_c == S1)
    send_en <= 1'd1;
  else
    send_en <= 1'd0;
end

assign w_uart_en = send_en;


endmodule